package yl.hs.bmipfull.service.production.impl;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yl.hs.bmipfull.daos.flow.IFlowDataDao;
import yl.hs.bmipfull.daos.flow.IFlowUserTaskDao;
import yl.hs.bmipfull.daos.laboratory.IPackageInfoDao;
import yl.hs.bmipfull.daos.material.IWarehouseDao;
import yl.hs.bmipfull.daos.production.IFinishProductInventoryDao;
import yl.hs.bmipfull.daos.production.IFinishProductWarehouseRecordDao;
import yl.hs.bmipfull.pojo.material.WarehouseEntity;
import yl.hs.bmipfull.pojo.production.FinishProductInventoryEntity;
import yl.hs.bmipfull.pojo.production.FinishProductWarehouseRecordEntity;
import yl.hs.bmipfull.service.production.IFinishProductWarehouseRecordService;
import yl.hs.bmipfull.utils.DataState;
import yl.hs.bmipfull.utils.HsApp;
import yl.hs.bmipfull.utils.Tl;
import yl.hs.bmipfull.utils.datastate.ActionType;
import yl.hs.bmipfull.viewmodels.PageQuery;
import yl.hs.bmipfull.viewmodels.PageResult;
import yl.hs.bmipfull.viewmodels.production.FinishWareHouseModel;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 谢东
 * @apiNote 成品入库记录服务层接口实现
 * @since 2023年06月14日 11时44分27秒 <br/>
 */
@Service
public class FinishProductWarehouseRecordServiceImpl extends ProductionBaseService implements IFinishProductWarehouseRecordService {

    @Autowired
    IFinishProductWarehouseRecordDao dao;
    @Autowired
    IFinishProductInventoryDao inventoryDao;
    @Autowired
    IWarehouseDao warehouseDao;
    @Autowired
    IFlowDataDao dataDao;
    @Autowired
    IFlowUserTaskDao userTaskDao;
    @Autowired
    IPackageInfoDao packageInfoDao;

    @Override
    public List<FinishProductWarehouseRecordEntity> queryList(PageQuery pageQuery) throws Exception {
        pageQuery.checkSortSides(FinishProductWarehouseRecordEntity.class);
        return dao.queryPage(pageQuery.getQuery());
    }

    @Override
    public PageResult<FinishProductWarehouseRecordEntity> queryListFX(PageQuery pageQuery, int rowNum, int page) throws Exception {
        var user = HsApp.getCurrent();
        pageQuery.checkSortSides(FinishProductWarehouseRecordEntity.class);
        if(user!=null){
            pageQuery.getQuery().put("types", user.getType()==null?0:user.getType());
        }
        var totil = dao.queryPageFX(pageQuery.getQuery());
        pageQuery.getQuery().put("querySkip", (page - 1) * rowNum);
        pageQuery.getQuery().put("pageSize", rowNum);
        pageQuery.getQuery().put("sortKey", String.join(",", pageQuery.getSortSides()));
        PageResult<FinishProductWarehouseRecordEntity> result = new PageResult(rowNum);
        result.setRecords(dao.queryCountByConditionFX(pageQuery.getQuery()));
        result.setPage(page);
        result.setData(dao.queryPageFX(pageQuery.getQuery()));
        var totilquantity = totil.stream().map(s -> s.getQuantity()).reduce(BigDecimal::add);
        var totilweight = totil.stream().map(s -> s.getWeight()).reduce(BigDecimal::add);
        Map<String, Object> results = new HashMap<>();
        results.put("totilquantity", totilquantity);
        results.put("totilweight", totilweight);
        result.setObject(results);
        return result;
    }

    @Override
    public PageResult<FinishProductWarehouseRecordEntity> queryPage(PageQuery pageQuery, int rowNum, int page) throws Exception {
        var user = HsApp.getCurrent();
        pageQuery.checkSortSides(FinishProductWarehouseRecordEntity.class);
        if(user!=null){
            pageQuery.getQuery().put("types", user.getType()==null?0:user.getType());
        }
        var totil = dao.queryPage(pageQuery.getQuery());
        pageQuery.getQuery().put("querySkip", (page - 1) * rowNum);
        pageQuery.getQuery().put("pageSize", rowNum);
        pageQuery.getQuery().put("sortKey", String.join(",", pageQuery.getSortSides()));
        PageResult<FinishProductWarehouseRecordEntity> result = new PageResult(rowNum);
        result.setRecords(dao.queryCountByCondition(pageQuery.getQuery()));
        result.setPage(page);
        result.setData(dao.queryPage(pageQuery.getQuery()));
        var totilquantity = totil.stream().map(s -> s.getQuantity()).reduce(BigDecimal::add);
        var totilweight = totil.stream().map(s -> s.getWeight()).reduce(BigDecimal::add);
        Map<String, Object> results = new HashMap<>();
        results.put("totilquantity", totilquantity);
        results.put("totilweight", totilweight);
        result.setObject(results);
        return result;
    }


    @Override
    public FinishProductWarehouseRecordEntity findBySn(String sn) {
        return dao.findBySN(sn);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer saveFinishProductWarehouseRecord(Map<String, Object> model, String sn) throws Exception {
        Integer result = 0;
        FinishProductWarehouseRecordEntity entity = null;
        if (Tl.isEmpty(sn)) {
            //执行保存
            entity = new FinishProductWarehouseRecordEntity();
            Tl.getChangeLog(entity, model);
            entity.setPYFieldValue();
            entity.setSn(queryNewSN(FinishProductWarehouseRecordEntity.class));
            result = dao.insertNew(entity);
            if (result > 0) {
                //createInventory(entity);
                if (entity.getType() == 0) {
                    writeLog(ActionType.CREATE, entity.getSn(), "插入成品入库记录信息", Tl.toJson(entity), FinishProductWarehouseRecordEntity.class);
                } else if (entity.getType() == 1) {
                    writeLog(ActionType.CREATE, entity.getSn(), "插入成品损耗记录信息", Tl.toJson(entity), FinishProductWarehouseRecordEntity.class);
                } else {
                    writeLog(ActionType.CREATE, entity.getSn(), "插入成品出库记录信息", Tl.toJson(entity), FinishProductWarehouseRecordEntity.class);
                }
            }
        } else {
            //执行修改
            entity = findBySn(sn);
            Tl.getChangeLog(entity, model);
            entity.setPYFieldValue();
            result = dao.update(entity);
            if (result > 0) {
                writeLog(ActionType.UPDATE, sn, "更新成品入库记录信息", Tl.toJson(entity), FinishProductWarehouseRecordEntity.class);
            }
        }

        return result;
    }

    @Override
    public Integer saveListFinishProductWarehouseRecord(FinishWareHouseModel model) throws Exception {
        var data = model.getData();
        data.forEach(s -> {
            s.setSn(queryNewSN(FinishProductWarehouseRecordEntity.class));
            Integer result = dao.insertNew(s);
            if (result > 0) {
                //createInventory(entity);
                if (s.getType() == 0) {
                    writeLog(ActionType.CREATE, s.getSn(), "插入成品入库记录信息", Tl.toJson(s), FinishProductWarehouseRecordEntity.class);
                } else if (s.getType() == 1) {
                    writeLog(ActionType.CREATE, s.getSn(), "插入成品损耗记录信息", Tl.toJson(s), FinishProductWarehouseRecordEntity.class);
                } else {
                    writeLog(ActionType.CREATE, s.getSn(), "插入成品出库记录信息", Tl.toJson(s), FinishProductWarehouseRecordEntity.class);
                }
            }
        });
        return 1;
    }

    private void createInventory(FinishProductWarehouseRecordEntity recordEntity) {
        var productInventory = inventoryDao.findByWareHouseSNAndProductSN(recordEntity.getWareHouseSN(), recordEntity.getProductSN(), recordEntity.getPackageName(), recordEntity.getPackageSN());
        if (productInventory != null) {
            var query = productInventory.getWeight();
            //修改成品库存数量
            if (recordEntity.getType() == 0) {
                productInventory.setWeight(productInventory.getWeight().add(recordEntity.getWeight()));
                productInventory.setQuantity(productInventory.getQuantity().add(recordEntity.getQuantity()));
            } else {
                productInventory.setWeight(productInventory.getWeight().subtract(recordEntity.getWeight()));
                productInventory.setQuantity(productInventory.getQuantity().subtract(recordEntity.getQuantity()));
            }
            inventoryDao.update(productInventory);
            if (recordEntity.getType() == 0) {
                writeLog(ActionType.UPDATE, productInventory.getSn(), "创建入库记录增加库存，库存从" + query.setScale(2, RoundingMode.DOWN) + "变为" + productInventory.getWeight().setScale(2, RoundingMode.DOWN) + ",入库记录编号为" + recordEntity.getSn(), null, FinishProductInventoryEntity.class);
            } else if (recordEntity.getType() == 1) {
                writeLog(ActionType.UPDATE, productInventory.getSn(), "创建损耗记录减少库存，库存从" + query.setScale(2, RoundingMode.DOWN) + "变为" + productInventory.getWeight().setScale(2, RoundingMode.DOWN) + ",出库记录编号为" + recordEntity.getSn(), null, FinishProductInventoryEntity.class);
            } else {
                writeLog(ActionType.UPDATE, productInventory.getSn(), "创建出库记录减少库存，库存从" + query.setScale(2, RoundingMode.DOWN) + "变为" + productInventory.getWeight().setScale(2, RoundingMode.DOWN) + ",损耗记录编号为" + recordEntity.getSn(), null, FinishProductInventoryEntity.class);
            }

        } else {
            //新建成品库存信息
            if (recordEntity.getType() == 0) {
                FinishProductInventoryEntity inventoryEntity = new FinishProductInventoryEntity();
                inventoryEntity.setSn(queryNewSN(FinishProductInventoryEntity.class));
                inventoryEntity.setProductName(recordEntity.getProductName());
                inventoryEntity.setProductSN(recordEntity.getProductSN());
                inventoryEntity.setProductSpec(recordEntity.getProductSpec());
                inventoryEntity.setWareHouseName(recordEntity.getWareHouseName());
                inventoryEntity.setWareHouseSN(recordEntity.getWareHouseSN());
                inventoryEntity.setQuantity(recordEntity.getQuantity());
                inventoryEntity.setWeight(recordEntity.getWeight());
                inventoryEntity.setState((short) 2);
                inventoryEntity.setPackageSN(recordEntity.getPackageSN());
                inventoryEntity.setPackageName(recordEntity.getPackageName());
                inventoryDao.insertNew(inventoryEntity);
                writeLog(ActionType.CREATE, inventoryEntity.getSn(), "创建入库记录增加库存,库存由" + recordEntity.getWeight() + ",入库记录编号为" + recordEntity.getSn(), null, FinishProductInventoryEntity.class);
            }
        }
        var warehouse = warehouseDao.findBySN(recordEntity.getWareHouseSN());
        if (warehouse != null) {
            var query = warehouse.getInventory();
            var inventory = warehouse.getInventory();
            if (recordEntity.getType() == 0) {
                inventory = inventory.add(recordEntity.getWeight());
                writeLog(ActionType.CREATE, warehouse.getSn(), "创建入库记录增加库存,库存由" + query.setScale(2, RoundingMode.DOWN) + "变为" + inventory.setScale(2, RoundingMode.DOWN) + ",入库记录编号为" + recordEntity.getSn(), null, WarehouseEntity.class);
            } else if (recordEntity.getType() == 1) {
                inventory = inventory.subtract(recordEntity.getWeight());
                writeLog(ActionType.CREATE, warehouse.getSn(), "创建损耗记录减少库存,库存由" + query.setScale(2, RoundingMode.DOWN) + "变为" + inventory.setScale(2, RoundingMode.DOWN) + ",入库记录编号为" + recordEntity.getSn(), null, WarehouseEntity.class);
            } else {
                inventory = inventory.subtract(recordEntity.getWeight());
                writeLog(ActionType.CREATE, warehouse.getSn(), "创建出库记录减少库存,库存由" + query.setScale(2, RoundingMode.DOWN) + "变为" + inventory.setScale(2, RoundingMode.DOWN) + ",入库记录编号为" + recordEntity.getSn(), null, WarehouseEntity.class);
            }
            warehouse.setInventory(inventory);
            warehouseDao.update(warehouse);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer delete(String[] sn) {
        for (String s : sn) {
            var entity = dao.findBySN(s);
            if (entity.getState() == -1) {
                return 0;
            }
        }
        for (String s : sn) {
            FinishProductWarehouseRecordEntity ss = dao.findBySN(s);
            if (ss != null && ss.getRemark()!="对装出货") {
                userTaskDao.updateStateByObjectSN(ss.getSn());
                var productInventory = inventoryDao.findByWareHouseSNAndProductSN(ss.getWareHouseSN(), ss.getProductSN(), ss.getPackageName(), ss.getPackageSN());
                if (productInventory != null && ss.getState() == 2) {
                    var weight = productInventory.getWeight();
                    if (ss.getType() == 0) {
                        productInventory.setQuantity(productInventory.getQuantity().subtract(ss.getQuantity()));
                        productInventory.setWeight(productInventory.getWeight().subtract(ss.getWeight()));
                        writeLog(ActionType.UPDATE, productInventory.getSn(), "删除入库记录减少库存，库存由" + weight.setScale(2, RoundingMode.DOWN)
                                        + "变为" + productInventory.getWeight().setScale(2, RoundingMode.DOWN) + ",入库记录编号为" + ss.getSn()
                                        + "&&" + ss.getTruckPlate() + "&&" + productInventory.getWeight().setScale(2, RoundingMode.DOWN).subtract(weight.setScale(2, RoundingMode.DOWN)),
                                null, FinishProductInventoryEntity.class);
                        //writeLog(ActionType.DELETE, productInventory.getSn(), "删除入库记录减少库存,库存由" + weight.setScale(2, RoundingMode.DOWN) + "变为" + productInventory.getWeight().setScale(2, RoundingMode.DOWN) + ",入库记录编号为" + ss.getSn(), null, FinishProductInventoryEntity.class);
                    } else if (ss.getType() == 1) {
                        productInventory.setQuantity(productInventory.getQuantity().add(ss.getQuantity()));
                        productInventory.setWeight(productInventory.getWeight().add(ss.getWeight()));
                        writeLog(ActionType.UPDATE, productInventory.getSn(), "删除损耗记录增加库存，库存由" + weight.setScale(2, RoundingMode.DOWN)
                                        + "变为" + productInventory.getWeight().setScale(2, RoundingMode.DOWN) + ",出库记录编号为" + ss.getSn()
                                        + "&&" + ss.getTruckPlate() + "&&" + weight.setScale(2, RoundingMode.DOWN).subtract(productInventory.getWeight().setScale(2, RoundingMode.DOWN)),
                                null, FinishProductInventoryEntity.class);
                        //writeLog(ActionType.DELETE, productInventory.getSn(), "删除损耗记录增加库存,库存由" + weight.setScale(2, RoundingMode.DOWN) + "变为" + productInventory.getWeight().setScale(2, RoundingMode.DOWN) + ",损耗记录编号为" + ss.getSn(), null, FinishProductInventoryEntity.class);
                    } else {
                        productInventory.setQuantity(productInventory.getQuantity().add(ss.getQuantity()));
                        productInventory.setWeight(productInventory.getWeight().add(ss.getWeight()));
                        writeLog(ActionType.UPDATE, productInventory.getSn(), "删除出库记录增加库存，库存由" + weight.setScale(2, RoundingMode.DOWN)
                                        + "变为" + productInventory.getWeight().setScale(2, RoundingMode.DOWN) + ",损耗记录编号为" + ss.getSn()
                                        + "&&" + ss.getTruckPlate() + "&&" + weight.setScale(2, RoundingMode.DOWN).subtract(productInventory.getWeight().setScale(2, RoundingMode.DOWN)),
                                null, FinishProductInventoryEntity.class);
                        //writeLog(ActionType.DELETE, productInventory.getSn(), "删除出库记录增加库存,库存由" + weight.setScale(2, RoundingMode.DOWN) + "变为" + productInventory.getWeight().setScale(2, RoundingMode.DOWN) + ",出库记录编号为" + ss.getSn(), null, FinishProductInventoryEntity.class);
                    }
                    inventoryDao.update(productInventory);
                    //writeLog(ActionType.DELETE, productInventory.getSn(), "删除入库记录减少库存" + ss.getWeight() + ",入库记录编号为" + ss.getSn(), null, FinishProductInventoryEntity.class);
                }
                var warehouse = warehouseDao.findBySN(ss.getWareHouseSN());
                if (warehouse != null && ss.getState() == 2) {
                    var inventory = warehouse.getInventory();
                    var weight = warehouse.getInventory();
                    if (ss.getType() == 0) {
                        inventory = inventory.subtract(ss.getQuantity());
                        warehouse.setInventory(inventory);
                        writeLog(ActionType.DELETE, warehouse.getSn(), "删除入库记录减少库存,库存由" + weight + "变为" + warehouse.getInventory() + ",入库记录编号为" + ss.getSn(), null, WarehouseEntity.class);
                    } else if (ss.getType() == 1) {
                        inventory = inventory.add(ss.getQuantity());
                        warehouse.setInventory(inventory);
                        writeLog(ActionType.DELETE, warehouse.getSn(), "删除损耗记录增加库存,库存由" + weight + "变为" + warehouse.getInventory() + ",入库记录编号为" + ss.getSn(), null, WarehouseEntity.class);
                    } else {
                        inventory = inventory.add(ss.getQuantity());
                        warehouse.setInventory(inventory);
                        writeLog(ActionType.DELETE, warehouse.getSn(), "删除出库记录增加库存,库存由" + weight + "变为" + warehouse.getInventory() + ",入库记录编号为" + ss.getSn(), null, WarehouseEntity.class);
                    }
                    warehouseDao.update(warehouse);
                }
            }
        }
        Integer result = dao.changeStateBySN(sn, DataState.DELETED.code);
        writeLog(ActionType.DELETE, sn, FinishProductWarehouseRecordEntity.class);
        return result;
    }

    @Override
    public Integer insert(FinishProductWarehouseRecordEntity entity) {
        return dao.insertNew(entity);
    }

    @Override
    public Integer returnGoods(String sn, BigDecimal weight,String remark) {
        try {
            var entity = dao.findBySN(sn);
            var page = packageInfoDao.findBySN(entity.getPackageSN());
            entity.setWeight(entity.getWeight().subtract(weight));
            entity.setQuantity(entity.getQuantity().subtract(weight.multiply(new BigDecimal(1000)).divide(page.getPackWeight())));
            dao.updateByWeight (entity);
            writeLog(ActionType.CREATE, entity.getSn(), "创建成品退库信息，发货重量减少"+weight, Tl.toJson(entity), FinishProductWarehouseRecordEntity.class);
            FinishProductWarehouseRecordEntity ss = new FinishProductWarehouseRecordEntity();
            ss.setSn(queryNewSN(FinishProductWarehouseRecordEntity.class));
            ss.setRkState(2);
            ss.setType((short) 0);
            ss.setState((short) 2);
            ss.setQuantity(weight.multiply(new BigDecimal(1000)).divide(page.getPackWeight()));
            ss.setInTime(new Date());
            ss.setWeight(weight);
            ss.setWareHouseSN(entity.getWareHouseSN());
            ss.setWareHouseName(entity.getWareHouseName());
            ss.setPackageSN(entity.getPackageSN());
            ss.setPackageName(entity.getPackageName());
            ss.setProductName(entity.getProductName());
            ss.setProductCateName(entity.getProductCateName());
            ss.setProductSN(entity.getProductSN());
            ss.setTeams(entity.getTeams());
            ss.setRemark(remark);
            ss.setProductCateSN(entity.getProductCateSN());
            writeLog(ActionType.CREATE, ss.getSn(), "插入成品退库记录信息", Tl.toJson(ss), FinishProductWarehouseRecordEntity.class);
            return dao.insertNew(ss);
        }catch (Exception ee){
            return 0;
        }
    }
}